package com.example.myapplication.kotlin

fun main() {
    // 如果有次构造函数，可以通过多种不同的形式进行实例化
    val p = Person("小王")
    println(p.name)
    val p2 = Person("小王", 18)
    println(p2.name + p2.age)
    // 会先调用 Person("小王", 18)，再间接调用主构造函数
    val p3 = Person("小王", 18, "中国")
    println(p3.name + p3.age + p3.country)
}


/*
constructor 后面写了属性，类的内部可以省略不写
比如说：class Person constructor(name: String) {
        var name: String = name  // 需要重复声明
      }
 */
//【主构造函数】- 接收姓名参数，直接声明为可变属性
class Person constructor(var name: String) {
    // 不需要再声明 name 属性，因为已经在构造函数中声明了
    var age: Int = 0
    var country: String = ""

    // init块会在每次创建对象时自动执行,可以写一些逻辑
    init {
        //  println("创建了Person对象，姓名: $name")
        /* require方法: require(布尔值){ false时的错误信息 } */
        require(name.isNotEmpty()) { "姓名不能为空" }
        require(age >= 0) { "年龄不能为负数" }
    }

    //【次构造函数1】- 接收姓名和年龄，委托给主构造函数
    // : this(name) 表示调用主构造函数 Person(name: String)
    constructor(name: String, age: Int) : this(name) {
        this.age = age // 【赋值给 age 属性】
    }

    //【次构造函数2】- 接收姓名、年龄和国家，委托给次构造函数1
    // : this(name, age) 表示调用次构造函数1 Person(name: String, age: Int)
    constructor(name: String, age: Int, country: String) : this(name, age) {
        this.country = country //  【赋值给 country 属性】
    }
}

/*
委托的意义和作用
1. 代码复用
    避免在多个构造函数中重复相同的初始化逻辑
    主构造函数负责基础属性初始化，其他构造函数专注于特定参数

2. 确保初始化完整性
    通过委托链确保所有必要的初始化步骤都会被执行
    防止某些属性未被正确初始化

3. 维护一致的初始化顺序
    保证对象按照预定的顺序进行初始化
    避免初始化过程中的依赖问题

4. Kotlin 语言规范
    Kotlin 强制要求次构造函数必须直接或间接委托给主构造函数
    通过 : this(...) 语法实现构造函数间的委托调用
*/
